from tkinter import *
import pyaudio
import wave
import threading
import os
import sys


# 添加路径处理函数
def get_exe_directory():
    """获取exe文件所在的目录"""
    exe_path = os.path.abspath(sys.argv[0])
    return os.path.dirname(exe_path)


def get_resource_path(relative_path):
    """获取资源的完整路径（在exe同级目录中）"""
    exe_dir = get_exe_directory()
    return os.path.join(exe_dir, relative_path)


# 录音相关全局变量
recording = False
frames = []
audio = None
stream = None

# 音频参数
CHUNK = 1024
FORMAT = pyaudio.paInt16
CHANNELS = 1
RATE = 44100


# 修改load_script函数以支持新目录结构
def load_script():
    """从resources文件夹加载剧本文件"""
    script_path = get_resource_path(os.path.join('resources', 'script_resources.txt'))
    print(f"Loading script from: {script_path}")
    with open(script_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()
    return lines


def insert_lines_at_positions(filename, positions_and_contents):
    """
    在多个指定位置插入多行内容

    Args:
        filename (str): 文件名
        positions_and_contents (list): 包含(行号, 内容)元组的列表
    """
    # 使用新路径
    file_path = get_resource_path(os.path.join('resources', filename))

    with open(file_path, 'r', encoding='utf-8') as file:
        lines = file.readlines()

    # 按行号降序排序，避免插入影响后续位置
    positions_and_contents.sort(key=lambda x: x[0], reverse=True)

    for line_number, content in positions_and_contents:
        if 1 <= line_number <= len(lines) + 1:
            lines.insert(line_number - 1, content + '\n')

    with open(file_path, 'w', encoding='utf-8') as file:
        file.writelines(lines)


def auto_wrap(text, width=19):
    """最简单的文本自动换行函数"""
    result = []
    for i in range(0, len(text), width):
        result.append(text[i:i + width])
    return '\n'.join(result)


def toggle_recording():
    """切换录音状态"""
    global recording, frames

    if not recording:
        start_recording()
    else:
        stop_recording()


def start_recording():
    """开始录音"""
    global recording, frames, audio, stream

    recording = True
    frames = []

    # 更新界面
    record_btn.config(text="停止录音", bg="green")
    status_label.config(text="录音中...")

    # 初始化PyAudio
    audio = pyaudio.PyAudio()

    # 在新线程中录音
    recording_thread = threading.Thread(target=record_audio)
    recording_thread.start()


def stop_recording():
    """停止录音"""
    global recording

    recording = False
    record_btn.config(text="开始录音", bg="red")
    status_label.config(text="录音已保存为" + str(final[lb.curselection()[0]][0]) + "output.wav")


def record_audio():
    """录音函数"""
    global recording, frames, audio, stream

    stream = audio.open(
        format=FORMAT,
        channels=CHANNELS,
        rate=RATE,
        input=True,
        frames_per_buffer=CHUNK
    )

    while recording:
        data = stream.read(CHUNK)
        frames.append(data)

    stream.stop_stream()
    stream.close()
    audio.terminate()

    # 保存录音文件
    save_recording()


def refresh_listbox():
    # 清空Listbox和final
    lb.delete(0, END)
    final.clear()
    # 重新加载
    lines = load_script()
    i = 0
    for line in lines:
        line = line.strip()
        if line[0] != '{' and line[-1] != '}':
            lb.insert(END, str(i) + " : " + line)
            final.append([i, line])
        i += 1


def save_recording():
    """保存录音为WAV文件"""
    global frames, audio

    # 获取当前选中的行号
    selected_index = lb.curselection()[0]
    line_number = final[selected_index][0]

    # 确保music目录存在
    music_dir = get_resource_path('audio')
    if not os.path.exists(music_dir):
        os.makedirs(music_dir)

    # 保存录音文件到music目录
    filename = f"{line_number}output.wav"
    file_path = get_resource_path(os.path.join('audio', filename))

    wf = wave.open(file_path, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(audio.get_sample_size(FORMAT))
    wf.setframerate(RATE)
    wf.writeframes(b''.join(frames))
    wf.close()

    # 写入资源文件到resources目录
    muc_resources_path = get_resource_path(os.path.join('resources', 'muc_resources.txt'))
    with open(muc_resources_path, 'a+', encoding='utf-8') as file:
        write_str = f"\nvoice{line_number} {filename}"
        file.write(write_str)

    # 在脚本文件中插入voice命令
    # 在选中行前插入{voice add voiceX}
    # 在选中行后插入{voice remove voiceX}
    insertions = [
        (line_number + 1, f'{{voice add voice{line_number}}}'),
        (line_number + 2, f'{{voice remove voice{line_number}}}'),
    ]
    insert_lines_at_positions('script_resources.txt', insertions)
    refresh_listbox()


root = Tk()
root.title("gcgal_editor")
root.geometry("500x600")
# height=11设置listbox组件的高度，默认是10行。

global lines
lines = load_script()

record_frame = Frame(root)
record_frame.pack(pady=10)

record_btn = Button(
    record_frame,
    text="开始录音",
    command=toggle_recording,
    bg="red",
    fg="white",
    font=("Arial", 12),
    width=15,
    height=1
)
record_btn.pack(side=LEFT, padx=5)

status_label = Label(
    record_frame,
    text="准备录音",
    font=("Arial", 10)
)
status_label.pack(side=LEFT, padx=5)

sb = Scrollbar(root)
sb.pack(side="right", fill="y")

lb = Listbox(root, selectmode=BROWSE, width=50, yscrollcommand=sb.set)

lb.pack()
i = 0
final = []
for line in lines:
    line = line.strip()
    splitts = []
    if line[0] != '{' and line[-1] != '}':
        lb.insert(END, str(i) + " : " + line)
        final.append([i, line])
    i += 1

sb.config(command=lb.yview)
text_var = StringVar()
text_var.set("")

lab = Label(root, textvariable=text_var, wraplength=300)
lab.pack()


def select(event):
    print(lb.curselection()[0])
    text_var.set(final[lb.curselection()[0]][1])


lb.bind("<<ListboxSelect>>", select)

mainloop()